﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace ERPStore.Models
{
	/// <summary>
	/// Disponibilité d'un produit
	/// </summary>
	[Serializable]
	[DataContract]
	public class ProductStockInfo
	{
		public ProductStockInfo()
		{
			BackOrderInfoList = new List<BackOrderInfo>();
		}
		/// <summary>
		/// Code du produit
		/// </summary>
		/// <value>The code.</value>
		[DataMember]
		public string ProductCode { get; set; }
		/// <summary>
		/// Stock physique du produit
		/// </summary>
		/// <value>The physical stock.</value>
		[DataMember]
		public int PhysicalStock{ get; set; }
		/// <summary>
		/// Total de la quantité réservée par les clients
		/// </summary>
		/// <value>The reserved quantity.</value>
		[DataMember]
		public int ReservedQuantity { get; set; }
		/// <summary>
		/// Total de la quantité réservée chez les fournisseurs
		/// </summary>
		/// <value>The provisionned quantity.</value>
		[DataMember]
		public int ProvisionnedQuantity { get; set; }
		/// <summary>
		/// Nombre de jours de livraison
		/// </summary>
		/// <remarks>
		/// Si le produit est en stock, ajouter ce nombre de jour pour connaitre
		/// la date de livraison prevue chez le client depart de l'entrepot
		/// </remarks>
		/// <value>The delivery days count.</value>
		[DataMember]
		public int DeliveryDaysCount { get; set; }
		/// <summary>
		/// Nombre de jours avant reception dans l'entrepot
		/// </summary>
		/// <value>The provisionning days count.</value>
		[DataMember]
		public int ProvisionningDaysCount { get; set; }
		/// <summary>
		/// Prochaine date de reception prevue pour réappro
		/// </summary>
		/// <remarks>
		/// Cette valeur peut etre nulle s'il n'y a pas de réappro engagée
		/// </remarks>
		/// <value>The most provisionning date.</value>
		[DataMember]
		public DateTime? MostProvisionningDate { get; set; }
		/// <summary>
		/// Stock disponible
		/// </summary>
		/// <value>The available stock.</value>
		[DataMember] 
		public int AvailableStock { get; set; }

		/// <summary>
		/// Produit en fin de vie
		/// utiliser uniquement le reste du stock physique
		/// ensuite le produit passe non vendable
		/// </summary>
		[DataMember] 
		public bool EndOfLife { get; set; }

		/// <summary>
		/// Indique s'il y a du stock pour le produit
		/// </summary>
		/// <value><c>true</c> if this instance has stock; otherwise, <c>false</c>.</value>
		[DataMember] 
		public bool HasStock 
		{
			get
			{
				return AvailableStock > 0;
			}
			set
			{
				// For Serialization only
			}
		}
		/// <summary>
		/// Indique le temps total qu'il faut pour faire parvenir 
		/// le produit au client
		/// </summary>
		/// <remarks>
		/// Si la valeur est -1 alors ne pas vendre le produit, car pas configuré 
		/// pour la vente.
		/// </remarks>
		/// <value>The total provisionning day count.</value>
		[DataMember] 
		public int TotalProvisionningDayCount
		{
			get
			{
				if (ProvisionningDaysCount == -1)
				{
					return -1;
				}
				if (!HasStock)
				{
					return Math.Max(2, DeliveryDaysCount) + Math.Max(3,ProvisionningDaysCount);
				}
				return Math.Max(2, DeliveryDaysCount);
			}
			set
			{
				// For Serialization
			}
		}

		/// <summary>
		/// Indique textuellement la disponibilité du stock
		/// </summary>
		/// <value>The disponibility.</value>
		public string Disponibility
		{
			get
			{
				if (HasStock)
				{
					return string.Format("{0} en stock", AvailableStock);
				}
				if (TotalProvisionningDayCount < 0)
				{
					return "Nous contacter";
				}
				var plurial = (TotalProvisionningDayCount > 1) ? "s" : string.Empty;
				return string.Format("{0} jour{1}", TotalProvisionningDayCount, plurial);
			}
		}

		/// <summary>
		/// Indique la quantité minimale en stock
		/// </summary>
		/// <value>The minimal quantity.</value>
		[DataMember]
		public int MinimalQuantity { get; set; }

		[DataMember]
		public List<BackOrderInfo> BackOrderInfoList { get; set; }

		[DataMember]
		public bool IsComposite { get; set; }

		[DataMember]
		public ProvisioningStrategy ProvisioningStrategy { get; set; }

		public DateTime? GetNextShippingDate()
		{
			if (!this.HasStock
				&& this.TotalProvisionningDayCount == -1)
			{
				return null;
			}

			var totalDays = Math.Max(this.TotalProvisionningDayCount,1);
			var nextShippingDate = DateTime.Now.AddDays(1);

			var i = 1;
			while (i != totalDays)
			{
				nextShippingDate = nextShippingDate.AddDays(1);
				if (nextShippingDate.DayOfWeek == DayOfWeek.Saturday
					|| nextShippingDate.DayOfWeek == DayOfWeek.Sunday)
				{
					nextShippingDate = nextShippingDate.AddDays(1);
				}
				else
				{
					i++;
				}
			}

			return nextShippingDate;
		}
	}
}